package sys_ctrl

import (
	"crypto/md5"
	"fmt"
	"net/http"
	"ubt-aio-service/app/mod/sys_mod"
	"ubt-aio-service/app/pkg/code"
	"ubt-aio-service/app/pkg/parse"
	"ubt-aio-service/app/serv/sys_serv"
	"ubt-aio-service/app/utils"
)

type sysUser struct{}

var SysUserCtrl sysUser

// Login 用户登录
func (c *sysUser) Login(r *http.Request, w http.ResponseWriter) {
	req := &sys_mod.SysUserLoginReq{}
	// 将请求的参数转换为请求结构体
	if err := parse.Parse(r, req); err != "" {
		utils.ToJson(w, &utils.ResJson{Code: utils.ParamErr.Code, Msg: err})
		return
	}
	// 过滤关键参数值中的非法字符
	req.Usname = utils.InputFilter(req.Usname, true)
	req.Passwd = utils.InputFilter(req.Passwd, true)
	req.Chcode = utils.InputFilter(req.Chcode, true)
	// 获取图形验证码的字符并校验
	sysCode := code.GetCodeImg(r)
	if sysCode == "" || req.Chcode != sysCode {
		utils.ToJson(w, utils.ChkCodeErr)
		return
	}
	// 密码加密
	req.Passwd = fmt.Sprintf("%x", md5.Sum([]byte(req.Passwd)))
	// 登录并返回token
	var token string
	clientIp := utils.GetClientIP(r)
	res := sys_serv.SysUserServ.Login(r, req)
	if res.Code == utils.Succeed.Code {
		token = res.Data.(map[string]any)["token"].(string)
		logReq := &sys_mod.SysLogSaveReq{UserId: res.Data.(map[string]any)["userId"].(string), MenuCode: utils.SysUser, IpAddr: clientIp, Kind: 6}
		sys_serv.SysLogServ.Add(logReq)
	}
	utils.ToJson(w, &utils.ResJson{Code: res.Code, Msg: res.Msg, Data: token})
}

// Session 获取用户缓冲信息
func (c *sysUser) Session(r *http.Request, w http.ResponseWriter) {
	token := r.Header.Get(utils.Token)
	// 通过头部请求的token获取用户信息
	if userInfo := sys_serv.GetUserInfo(token); userInfo != nil {
		utils.ToJson(w, &utils.ResJson{Code: utils.Succeed.Code, Msg: utils.Succeed.Msg, Data: userInfo})
	} else {
		utils.ToJson(w, utils.NoLogin)
	}
}

// Exit 用户登出
func (c *sysUser) Exit(r *http.Request, w http.ResponseWriter) {
	token := r.Header.Get(utils.Token)
	// 判断缓冲中的用户信息是否为空，不为空则清空
	if userInfo := sys_serv.GetUserInfo(token); userInfo != nil {
		req := &sys_mod.SysUserExitReq{UserId: userInfo.UserId, Token: token}
		sys_serv.SysUserServ.Exit(req)
	}
	utils.ToJson(w, utils.Succeed)
}

// Save 保存用户
func (c *sysUser) Save(r *http.Request, w http.ResponseWriter) {
	// 通过头部请求的token获取用户信息
	token := r.Header.Get(utils.Token)
	userInfo := sys_serv.GetUserInfo(token)
	if userInfo == nil {
		utils.ToJson(w, utils.NoLogin)
		return
	}
	req := &sys_mod.SysUserSaveReq{}
	// 将请求的参数转换为请求结构体
	if err := parse.Parse(r, req); err != "" {
		utils.ToJson(w, &utils.ResJson{Code: utils.ParamErr.Code, Msg: err})
		return
	}
	// 过滤关键参数值中的非法字符
	req.UserId = utils.InputFilter(req.UserId, true)
	req.Usname = utils.InputFilter(req.Usname, true)
	req.NickName = utils.InputFilter(req.NickName, true)
	req.Mobile = utils.InputFilter(req.Mobile, true)
	req.RoleId = utils.InputFilter(req.RoleId, true)
	req.DeptId = utils.InputFilter(req.DeptId, true)
	// 判断用户密码
	passwd := req.Passwd
	userId := req.UserId
	if (userId == "" && (passwd == "" || len(passwd) < 6 || len(passwd) > 30)) || (userId != "" && passwd != "" && (len(passwd) < 6 || len(passwd) > 30)) {
		utils.ToJson(w, utils.PwdErr)
		return
	}
	// 判断编码是否重复
	extVo := &sys_mod.SysUserExtVo{UserId: req.UserId, Usname: req.Usname, Mobile: req.Mobile}
	if ext := sys_serv.SysUserServ.Exists(extVo); ext {
		utils.ToJson(w, utils.Exists)
		return
	}
	// 判断是否修改密码
	if req.Passwd != "" {
		req.Passwd = fmt.Sprintf("%x", md5.Sum([]byte(req.Passwd)))
	}
	var (
		res  *utils.ResJson
		kind uint8
	)
	if req.UserId == "" {
		// 新增
		res = sys_serv.SysUserServ.Add(req)
		kind = 1
	} else {
		// 修改
		res = sys_serv.SysUserServ.Update(req)
		kind = 3
	}
	if res.Code == utils.Succeed.Code {
		logReq := &sys_mod.SysLogSaveReq{UserId: userInfo.UserId, MenuCode: utils.SysUser, IpAddr: userInfo.ClientIp, Kind: kind}
		sys_serv.SysLogServ.Add(logReq)
	}
	utils.ToJson(w, res)
}

// Process 审核删除用户
func (c *sysUser) Process(r *http.Request, w http.ResponseWriter) {
	// 通过头部请求的token获取用户信息
	token := r.Header.Get(utils.Token)
	userInfo := sys_serv.GetUserInfo(token)
	if userInfo == nil {
		utils.ToJson(w, utils.NoLogin)
		return
	}
	req := &sys_mod.SysUserProReq{}
	// 将请求的参数转换为请求结构体
	if err := parse.Parse(r, req); err != "" {
		utils.ToJson(w, &utils.ResJson{Code: utils.ParamErr.Code, Msg: err})
		return
	}
	// 过滤关键参数值中的非法字符
	req.UserIds = utils.InputFilter(req.UserIds, true)
	res := sys_serv.SysUserServ.Process(req)
	if res.Code == utils.Succeed.Code {
		var kind uint8
		switch req.States {
		case 1:
			kind = 4
		case 3:
			kind = 5
		case 2:
			kind = 2
		default:
			kind = 2
		}
		logReq := &sys_mod.SysLogSaveReq{UserId: userInfo.UserId, MenuCode: utils.SysUser, IpAddr: userInfo.ClientIp, Kind: kind}
		sys_serv.SysLogServ.Add(logReq)
	}
	utils.ToJson(w, res)
}

// Mine 修改个人资料
func (c *sysUser) Mine(r *http.Request, w http.ResponseWriter) {
	// 通过头部请求的token获取用户信息
	token := r.Header.Get(utils.Token)
	userInfo := sys_serv.GetUserInfo(token)
	if userInfo == nil {
		utils.ToJson(w, utils.NoLogin)
		return
	}
	req := &sys_mod.SysUserInfoReq{}
	// 将请求的参数转换为请求结构体
	if err := parse.Parse(r, req); err != "" {
		utils.ToJson(w, &utils.ResJson{Code: utils.ParamErr.Code, Msg: err})
		return
	}
	// 过滤关键参数值中的非法字符
	req.UserId = utils.InputFilter(req.UserId, true)
	req.Usname = utils.InputFilter(req.Usname, true)
	req.OldPasswd = utils.InputFilter(req.OldPasswd, true)
	req.AgnPasswd = utils.InputFilter(req.AgnPasswd, true)
	req.NewPasswd = utils.InputFilter(req.NewPasswd, true)
	req.NickName = utils.InputFilter(req.NickName, true)
	if req.OldPasswd != "" {
		// 判断原密码是否正确
		req.OldPasswd = fmt.Sprintf("%x", md5.Sum([]byte(req.OldPasswd)))
		sysPasswd := sys_serv.SysUserServ.GetPasswd(req.UserId)
		if sysPasswd == "" || req.OldPasswd != sysPasswd {
			utils.ToJson(w, utils.OldPwdErr)
			return
		}
		// 判断两次输入的新密码是否一致
		if req.NewPasswd == "" || req.AgnPasswd == "" || req.NewPasswd != req.AgnPasswd || len(req.AgnPasswd) < 6 || len(req.AgnPasswd) > 30 {
			utils.ToJson(w, utils.TwoPwdErr)
			return
		}
		req.NewPasswd = fmt.Sprintf("%x", md5.Sum([]byte(req.NewPasswd)))
	}
	res := sys_serv.SysUserServ.Mine(req)
	if res.Code == utils.Succeed.Code {
		logReq := &sys_mod.SysLogSaveReq{UserId: userInfo.UserId, MenuCode: utils.Mine, IpAddr: userInfo.ClientIp, Kind: 3}
		sys_serv.SysLogServ.Add(logReq)
	}
	utils.ToJson(w, res)
}

// One 获取用户详情
func (c *sysUser) One(r *http.Request, w http.ResponseWriter) {
	// 通过头部请求的token获取用户信息
	token := r.Header.Get(utils.Token)
	userInfo := sys_serv.GetUserInfo(token)
	if userInfo == nil {
		utils.ToJson(w, utils.NoLogin)
		return
	}
	// 过滤关键参数值中的非法字符
	u := r.URL.Query()
	if u == nil {
		utils.ToJson(w, utils.ParamErr)
		return
	}
	userId := u.Get("userId")
	// 过滤关键参数值中的非法字符
	userId = utils.InputFilter(userId, true)
	if userId == "" || len(userId) != 21 {
		utils.ToJson(w, utils.ParamErr)
		return
	}
	res := sys_serv.SysUserServ.One(userId)
	utils.ToJson(w, res)
}

// Page 获取用户树状列表
func (c *sysUser) Page(r *http.Request, w http.ResponseWriter) {
	// 通过头部请求的token获取用户信息
	token := r.Header.Get(utils.Token)
	userInfo := sys_serv.GetUserInfo(token)
	if userInfo == nil {
		utils.ToJson(w, utils.NoLogin)
		return
	}
	// 过滤关键参数值中的非法字符
	u := r.URL.Query()
	if u == nil {
		utils.ToJson(w, utils.ParamErr)
		return
	}
	// 获取请求的参数
	keywords := u.Get("keywords")
	roleId := u.Get("roleId")
	deptId := u.Get("deptId")
	stateses := u.Get("states")
	limits := u.Get("limit")
	offsets := u.Get("offset")
	// 过滤关键参数值中的非法字符
	keywords = utils.InputFilter(keywords, false)
	roleId = utils.InputFilter(roleId, true)
	deptId = utils.InputFilter(deptId, true)
	stateses = utils.InputFilter(stateses, true)
	limits = utils.InputFilter(limits, true)
	offsets = utils.InputFilter(offsets, true)
	states := parse.Str2u8(stateses)
	limit := parse.Str2u8(limits)
	offset := parse.Str2u32(offsets)
	// 先统计信息的数量
	req := &sys_mod.SysUserPageReq{Keywords: keywords, RoleId: roleId, States: states, DeptId: deptId}
	res := sys_serv.SysUserServ.Count(req)
	if res.Code == utils.Succeed.Code {
		dto := &sys_mod.SysUserPageRes{Total: res.Data.(map[string]any)["nums"].(int64)}
		// 再查询具体的信息列表
		req.Limit = limit
		req.Offset = offset
		if res = sys_serv.SysUserServ.Page(req); res.Code == utils.Succeed.Code {
			dto.List = res.Data
			utils.ToJson(w, &utils.ResJson{Code: res.Code, Msg: res.Msg, Data: dto})
			return
		}
	}
	utils.ToJson(w, utils.NoData)
}

// Select 获取用户下拉列表
func (c *sysUser) Select(r *http.Request, w http.ResponseWriter) {
	// 通过头部请求的token获取用户信息
	token := r.Header.Get(utils.Token)
	userInfo := sys_serv.GetUserInfo(token)
	if userInfo == nil {
		utils.ToJson(w, utils.NoLogin)
		return
	}
	// 过滤关键参数值中的非法字符
	u := r.URL.Query()
	if u == nil {
		utils.ToJson(w, utils.ParamErr)
		return
	}
	// 获取请求的参数
	keywords := u.Get("keywords")
	deptId := u.Get("deptId")
	limits := u.Get("limit")
	offsets := u.Get("offset")
	// 过滤关键参数值中的非法字符
	keywords = utils.InputFilter(keywords, false)
	deptId = utils.InputFilter(deptId, true)
	limits = utils.InputFilter(limits, true)
	offsets = utils.InputFilter(offsets, true)
	limit := parse.Str2u8(limits)
	offset := parse.Str2u32(offsets)
	// 先统计信息的数量
	req := &sys_mod.SysUserSelReq{Keywords: keywords, DeptId: deptId}
	res := sys_serv.SysUserServ.SelCount(req)
	if res.Code == utils.Succeed.Code {
		dto := &sys_mod.SysUserPageRes{Total: res.Data.(map[string]any)["nums"].(int64)}
		// 再查询具体的信息列表
		req.Limit = limit
		req.Offset = offset
		if res = sys_serv.SysUserServ.SelPage(req); res.Code == utils.Succeed.Code {
			dto.List = res.Data
			utils.ToJson(w, &utils.ResJson{Code: res.Code, Msg: res.Msg, Data: dto})
			return
		}
	}
	utils.ToJson(w, utils.NoData)
}
